package com.cq.hd.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.constant.MsgConstant;
import com.cq.hd.common.entity.mq.NotifyMsgSendDto;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.exception.BusinessException;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.member.api.TbAppUserApi;
import com.cq.hd.member.api.TbBusinessAgentApi;
import com.cq.hd.member.api.vo.AppUserVo;
import com.cq.hd.member.api.vo.BusinessAgentVo;
import com.cq.hd.order.api.dto.*;
import com.cq.hd.order.api.vo.*;
import com.cq.hd.order.config.LockUtils;
import com.cq.hd.order.convert.GroupBuyOrderConvert;
import com.cq.hd.order.mapper.*;
import com.cq.hd.order.mq.provider.NotifyMsgProvider;
import com.cq.hd.order.mq.provider.OrderRefundMsgProvider;
import com.cq.hd.order.param.GroupOrderSuccessParam;
import com.cq.hd.order.param.OrderStateUpdateParam;
import com.cq.hd.order.po.*;
import com.cq.hd.order.processor.order.OrderSubsidyRecalculateProcessor;
import com.cq.hd.order.service.OrderStateService;
import com.cq.hd.order.service.TbGroupBuyOrderService;
import com.cq.hd.order.service.TbOrderService;
import com.cq.hd.order.utils.OrderEnrollInfoUtil;
import com.cq.hd.order.utils.UsernameGenerator;
import com.cq.hd.product.api.TbActiveApi;
import com.cq.hd.product.api.vo.ActiveGroupBuyVo;
import com.cq.hd.product.api.vo.ActiveVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jdk.nashorn.internal.ir.IfNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author much
 * @since 2024/09/16 11:27
 */
@Slf4j
@Service
public class TbGroupBuyOrderServiceImpl implements TbGroupBuyOrderService {

    @Resource
    private TbActiveApi activeApi;
    @Resource
    private TbGroupBuyOrderMapper groupBuyOrderMapper;
    @Resource
    private TbGroupBuyOrderItemMapper groupBuyOrderItemMapper;
    @Resource
    private TbOrderMapper orderMapper;
    @Resource
    private TbOrderItemMapper orderItemMapper;
    @Resource
    private TbOrderRefundMapper orderRefundMapper;
    @Resource
    private OrderStateService orderStateService;
    @Lazy
    @Resource
    private TbOrderService orderService;
    @Resource
    private OrderSubsidyRecalculateProcessor orderSubsidyRecalculateProcessor;
    @Resource
    private TbAppUserApi appUserApi;
    @Resource
    private TbBusinessAgentApi businessAgentApi;
    @Resource
    private NotifyMsgProvider notifyMsgProvider;
    @Resource
    private OrderRefundMsgProvider orderRefundMsgProvider;
    @Resource
    private PlatformTransactionManager transactionManager;

    @Override
    public TbGroupBuyOrderPo getById(Long groupBuyOrderId) {
        return groupBuyOrderMapper.selectById(groupBuyOrderId);
    }

    @Transactional
    @Override
    public void createGroupBuyOrder(CreateGroupBuyOrderDto createGroupBuyOrderDto) {
        // 开团权限
        validateGroupCreatorPermission(createGroupBuyOrderDto.getActiveId(), createGroupBuyOrderDto.getUserId());

        ActiveGroupBuyVo activeGroupBuyVo = activeApi.getGroupBuyActiveByActiveId(createGroupBuyOrderDto.getActiveId()).unpack();
        ActiveVo activeVo = activeApi.getById(activeGroupBuyVo.getActiveId()).unpack();
        createGroupBuyOrderDto.setActiveTitle(activeVo.getActiveTitle());
        Long userId = createGroupBuyOrderDto.getUserId();
        AppUserVo appUserVo = appUserApi.getById(userId).unpack();


        // 拼团主单
        TbGroupBuyOrderPo groupBuyOrderPo = GroupBuyOrderConvert.wrapGroupBuyOrderPo(createGroupBuyOrderDto, activeGroupBuyVo, appUserVo);
        groupBuyOrderMapper.insert(groupBuyOrderPo);
        // 拼团子单
        TbGroupBuyOrderItemPo groupBuyOrderItemPo = GroupBuyOrderConvert.wrapGroupBuyOrderItemPo(groupBuyOrderPo, createGroupBuyOrderDto, appUserVo);
        groupBuyOrderItemMapper.insert(groupBuyOrderItemPo);
    }

    @Transactional
    @Override
    public Long createZeroGroupBuyOrder(CreateZeroGroupBuyOrderDto createZeroGroupBuyOrderDto) {
        Long activeId = createZeroGroupBuyOrderDto.getActiveId();
        Long userId = createZeroGroupBuyOrderDto.getUserId();

        validateGroupCreatorPermission(activeId, userId);

        ActiveGroupBuyVo activeGroupBuyVo = activeApi.getGroupBuyActiveByActiveId(activeId).unpack();
        ActiveVo activeVo = activeApi.getById(activeGroupBuyVo.getActiveId()).unpack();
        createZeroGroupBuyOrderDto.setActiveTitle(activeVo.getActiveTitle());
        AppUserVo appUserVo = appUserApi.getById(userId).unpack();

        if (activeGroupBuyVo.getLeadFreeEnabled() == 0) {
            Throw.isBusinessException("当前活动不支持0元开团");
        }

        // 拼团主单
        TbGroupBuyOrderPo groupBuyOrderPo = GroupBuyOrderConvert.wrapZeroGroupBuyOrderPo(createZeroGroupBuyOrderDto, activeGroupBuyVo, appUserVo);
        groupBuyOrderMapper.insert(groupBuyOrderPo);

        // 拼团子单
        TbGroupBuyOrderItemPo groupBuyOrderItemPo = GroupBuyOrderConvert.wrapZeroGroupBuyOrderItemPo(groupBuyOrderPo, createZeroGroupBuyOrderDto, appUserVo);
        groupBuyOrderItemMapper.insert(groupBuyOrderItemPo);

        return groupBuyOrderItemPo.getId();
    }

    @Transactional
    @Override
    public void joinGroup(Long groupBuyOrderId, CreateGroupBuyOrderDto createGroupBuyOrderDto) {
        TbGroupBuyOrderPo groupBuyOrderPo = Optional.ofNullable(getById(groupBuyOrderId))
                .orElseThrow(() -> new BusinessException("拼团不存在"));
        validateGroupBuyOrder(groupBuyOrderPo);

        Long userId = createGroupBuyOrderDto.getUserId();
        AppUserVo appUserVo = appUserApi.getById(userId).unpack();

        GroupBuyOrderItemQueryDto groupBuyOrderItemQueryDto = new GroupBuyOrderItemQueryDto();
        groupBuyOrderItemQueryDto.setGroupBuyOrderId(groupBuyOrderId);
        groupBuyOrderItemQueryDto.setUserId(userId);
        groupBuyOrderItemQueryDto.setStatusList(Arrays.asList(GroupBuyOrderItemStatusEnum.WAIT_PAY.getValue(), GroupBuyOrderItemStatusEnum.PAID.getValue()));
        List<TbGroupBuyOrderItemPo> tbGroupBuyOrderItemPos = groupBuyOrderItemMapper.selectByDto(groupBuyOrderItemQueryDto);
        if (CollectionUtils.isNotEmpty(tbGroupBuyOrderItemPos)) {
            Throw.isBusinessException("您已参加过该团");
        }

        ActiveVo activeVo = activeApi.getById(groupBuyOrderPo.getActiveId()).unpack();
        createGroupBuyOrderDto.setActiveTitle(activeVo.getActiveTitle());

        TbGroupBuyOrderItemPo groupBuyOrderItemPo = GroupBuyOrderConvert.wrapGroupBuyOrderItemPo(groupBuyOrderPo, createGroupBuyOrderDto, appUserVo);
        groupBuyOrderItemMapper.insert(groupBuyOrderItemPo);

        int res = groupBuyOrderMapper.increaseCurrentNum(groupBuyOrderId);
        if (res == 0) {
            throw new BusinessException("拼团已满员");
        }
    }

    @Override
    public void cancel(Long orderId) {
        LambdaQueryWrapper<TbGroupBuyOrderItemPo> qw = Wrappers.<TbGroupBuyOrderItemPo>lambdaQuery()
                .eq(TbGroupBuyOrderItemPo::getOrderId, orderId);
        TbGroupBuyOrderItemPo groupBuyOrderItemPo = groupBuyOrderItemMapper.selectOne(qw);
        groupBuyOrderItemPo.setStatus(GroupBuyOrderItemStatusEnum.CANCEL.getValue());
        groupBuyOrderItemPo.setUpdateTime(LocalDateTime.now());
        groupBuyOrderItemMapper.updateById(groupBuyOrderItemPo);

        // 释放拼团名额
        groupBuyOrderMapper.subCurrentNum(groupBuyOrderItemPo.getGroupBuyOrderId());

        // 如果是团长取消（超时未付款），则拼团取消
        if (groupBuyOrderItemPo.getGroupLead() == 1) {
            TbGroupBuyOrderPo groupBuyOrderPo = new TbGroupBuyOrderPo();
            groupBuyOrderPo.setId(groupBuyOrderItemPo.getGroupBuyOrderId());
            groupBuyOrderPo.setStatus(GroupBuyStatusEnum.FAILED.getValue());
            groupBuyOrderPo.setUpdateTime(LocalDateTime.now());
            groupBuyOrderMapper.updateById(groupBuyOrderPo);
        }

    }

    @Override
    public void updateGroupAfterPayment(Long orderId) {
        log.info("Update Group After Payment, orderId = {}", orderId);
        TbGroupBuyOrderItemPo groupBuyOrderItemPo = groupBuyOrderItemMapper.selectByOrderId(orderId);
        if (groupBuyOrderItemPo == null) {
            log.error("TbGroupBuyOrderItem not found");
            return;
        }
        GroupOrderSuccessParam groupOrderSuccessParam = new GroupOrderSuccessParam();
        groupOrderSuccessParam.setGroupBuyOrderItem(groupBuyOrderItemPo);
        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());
        try {
            // 如果是团长，更新主单状态为待成团
            if (groupBuyOrderItemPo.getGroupLead() == 1) {
                TbGroupBuyOrderPo groupBuyOrderPo = new TbGroupBuyOrderPo();
                groupBuyOrderPo.setId(groupBuyOrderItemPo.getGroupBuyOrderId());
                groupBuyOrderPo.setStatus(GroupBuyStatusEnum.PENDING.getValue());
                groupBuyOrderPo.setUpdateTime(LocalDateTime.now());
                groupBuyOrderMapper.updateById(groupBuyOrderPo);
            }

            // 更新拼团订单状态
            groupBuyOrderItemPo.setStatus(GroupBuyOrderItemStatusEnum.PAID.getValue());
            groupBuyOrderItemPo.setPaymentStatus(2);
            groupBuyOrderItemPo.setUpdateTime(LocalDateTime.now());
            groupBuyOrderItemMapper.updateById(groupBuyOrderItemPo);
            // 判断是否成团
            processForGroupSuccess(groupBuyOrderItemPo.getGroupBuyOrderId(), groupOrderSuccessParam);

            transactionManager.commit(transaction);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            transactionManager.rollback(transaction);
        }

        // 判断是否存在免单
        if (groupOrderSuccessParam.getRefundId() != null) {
            orderRefundMsgProvider.sendMsg(groupOrderSuccessParam.getRefundId());
        }
    }

    private void processForGroupSuccess(Long groupBuyOrderId, GroupOrderSuccessParam groupOrderSuccessParam) {
        // 是否成团
        TbGroupBuyOrderPo groupBuyOrderPo = groupBuyOrderMapper.selectById(groupBuyOrderId);
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "groupOrder:" + groupBuyOrderId);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);
            List<TbGroupBuyOrderItemPo> groupBuyOrderItems = groupBuyOrderItemMapper.selectByGroupBuyOrderId(groupBuyOrderId);
            long paidCount = groupBuyOrderItems.stream()
                    .filter(e -> e.getStatus() == GroupBuyOrderItemStatusEnum.PAID.getValue())
                    .count();
            // 成团
            if (paidCount == groupBuyOrderPo.getGroupNum()) {
                groupBuyOrderPo.setStatus(GroupBuyStatusEnum.COMPLETED.getValue());
                groupBuyOrderPo.setUpdateTime(LocalDateTime.now());
                groupBuyOrderPo.setGroupTime(LocalDateTime.now());
                groupBuyOrderMapper.updateById(groupBuyOrderPo);
                // 更新订单状态 -> 待核销
                updateOrderStateToWaitVerify(groupBuyOrderItems);
                // 成团免单处理
                selectFreeOrder(groupBuyOrderPo, groupBuyOrderItems, groupOrderSuccessParam);
                // 成团通知
                notifyGroupSuccess(groupBuyOrderItems);
            } else if (paidCount > groupBuyOrderPo.getGroupNum()) {
                // 拼团满员：取消订单 & 退款
                cancelOrder(groupOrderSuccessParam.getGroupBuyOrderItem(), true);
            }

        } catch (Exception e) {
            log.error("拼团订单支付成功处理异常：" + e.getMessage(), e);
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    private void notifyGroupSuccess(List<TbGroupBuyOrderItemPo> groupBuyOrderItems) {
        List<TbGroupBuyOrderItemPo> paidGroupItems = groupBuyOrderItems.stream()
                .filter(e -> GroupBuyOrderItemStatusEnum.PAID.getValue() == e.getStatus())
                .collect(Collectors.toList());

        for (TbGroupBuyOrderItemPo item : paidGroupItems) {
            NotifyMsgSendDto notifyMsgSendDto = new NotifyMsgSendDto();
            notifyMsgSendDto.setUserId(item.getUserId());
            notifyMsgSendDto.setRoleType(RoleTypeEnum.BUSINESS.getValue());
            notifyMsgSendDto.setMsgType(NotifyMsgTypeEnum.SUCCESSFUL_GROUP_BUY.getValue());
            String orderNo = StringUtils.isBlank(item.getOrderNo()) ? "0元开团" : item.getOrderNo();
            notifyMsgSendDto.setContent(String.format(MsgConstant.SUCCESSFUL_GROUP_BUY, item.getActiveTitle(), orderNo));
            notifyMsgSendDto.setMsgState(NotifyMsgStateEnum.NO_READ.getValue());
            notifyMsgProvider.sendMsg(notifyMsgSendDto);
        }
    }

    private void updateOrderStateToWaitVerify(List<TbGroupBuyOrderItemPo> groupItems) {
        for (TbGroupBuyOrderItemPo groupBuyOrderItemPo : groupItems) {
            if (GroupBuyOrderItemStatusEnum.PAID.getValue() == groupBuyOrderItemPo.getStatus()) {
                Long orderId = groupBuyOrderItemPo.getOrderId();
                if (orderId != null && orderId != 0) {
                    OrderStateUpdateParam orderStateUpdateParam = new OrderStateUpdateParam();
                    orderStateUpdateParam.setId(orderId);
                    orderStateUpdateParam.setOrgOrderState(OrderStateEnum.WAIT_GROUP.getValue());
                    orderStateService.paid(orderStateUpdateParam);
                }
            }
        }
    }

    // 抽取免单
    private void selectFreeOrder(
            TbGroupBuyOrderPo groupMainOrder, List<TbGroupBuyOrderItemPo> groupItems, GroupOrderSuccessParam groupOrderSuccessParam) {
        TbGroupBuyOrderItemPo freeItem = null;
        if (GroupBuyOrderFreeTypeEnum.LEAD_FREE.getValue() == groupMainOrder.getFreeType()) {
            // 团长免单
            Optional<TbGroupBuyOrderItemPo> findGroupLead = groupItems.stream().filter(e -> e.getGroupLead() == 1).findFirst();
            if (findGroupLead.isPresent()) {
                freeItem = findGroupLead.get();
            }
        } else if (GroupBuyOrderFreeTypeEnum.RANDOM_FREE.getValue() == groupMainOrder.getFreeType()) {
            // 随机免单
            List<TbGroupBuyOrderItemPo> paidItems = groupItems.stream()
                    .filter(e -> e.getStatus() == GroupBuyOrderItemStatusEnum.PAID.getValue())
                    .collect(Collectors.toList());
            Random random = new Random();
            int freeIndex = random.nextInt(paidItems.size());
            freeItem = paidItems.get(freeIndex);
        }

        if (freeItem != null) {
            // 更新子单
            freeItem.setFree(1);
            freeItem.setUpdateTime(LocalDateTime.now());
            groupBuyOrderItemMapper.updateById(freeItem);
            // 更新主单
            groupMainOrder.setFreeState(1);
            groupMainOrder.setUpdateTime(LocalDateTime.now());
            groupBuyOrderMapper.updateById(groupMainOrder);
            // 可能存在虚拟单，所以判断一下订单id
            if (freeItem.getOrderId() != null && freeItem.getOrderId() != 0) {
                // 重新计算订单补贴
                orderSubsidyRecalculateProcessor.recalculate4Free(freeItem.getOrderId());
                // 退款
                Long refundOrderId = orderRefund(freeItem.getOrderId());
                groupOrderSuccessParam.setRefundId(refundOrderId);

                // 免单通知
                String content = String.format(MsgConstant.FREE_GROUP_BUY, freeItem.getActiveTitle());
                sendNotifyMsg(
                        freeItem.getUserId(),
                        NotifyMsgTypeEnum.FREE_GROUP_BUY,
                        content);
            }
        }
    }

    private Long orderRefund(Long orderId) {
        TbOrderPo tbOrderPo = orderMapper.selectById(orderId);
        TbOrderRefundPo tbOrderRefundPo = new TbOrderRefundPo();
        tbOrderRefundPo.setBusinessId(tbOrderPo.getBusinessId());
        tbOrderRefundPo.setUserId(tbOrderPo.getUserId());
        tbOrderRefundPo.setOrderId(orderId);
        tbOrderRefundPo.setRefundType(RefundTypeEnum.GROUP_FREE.getValue());
        tbOrderRefundPo.setOrgReqDate(tbOrderPo.getHfReqDate());
        tbOrderRefundPo.setOrgReqSeqId(tbOrderPo.getHfReqSeqId());
        tbOrderRefundPo.setRefundAmt(tbOrderPo.getPayPrice());
        // 退款交易状态(1-待处理，2-处理中，3-成功，4-失败)
        tbOrderRefundPo.setRefundState(OrderRefundStateEnum.WAIT.getValue());
        tbOrderRefundPo.setRefundApplyTime(LocalDateUtil.getNowLocalDateTime());

        int insert = orderRefundMapper.insert(tbOrderRefundPo);
        if (insert == 0) {
            Throw.isBusinessException("生成退款单失败，orderId=" + orderId);
        }
        return tbOrderRefundPo.getId();
    }
    
    
    @Override
    public AppGroupBuyOrderDetailVo getAppGroupBuyOrderDetail(AppGroupBuyOrderDetailQueryDto appGroupBuyOrderDetailQueryDto) {
        Long orderId = appGroupBuyOrderDetailQueryDto.getOrderId();
        Long groupBuyOrderItemId = appGroupBuyOrderDetailQueryDto.getGroupBuyOrderItemId();
        Long userId = appGroupBuyOrderDetailQueryDto.getUserId();

        // 从下拼团下单后跳转过来groupBuyOrderItemId有值，从订单列表过来orderId有值
        if (orderId != null || groupBuyOrderItemId != null) {
            TbGroupBuyOrderItemPo groupBuyOrderItemPo = null;
            if (orderId != null) {
                groupBuyOrderItemPo = groupBuyOrderItemMapper.selectByOrderId(orderId);
            } else {
                groupBuyOrderItemPo = groupBuyOrderItemMapper.selectById(groupBuyOrderItemId);
            }
            if (groupBuyOrderItemPo == null) {
                Throw.isBusinessException("拼团订单不存在");
            }
            Long groupBuyOrderId = groupBuyOrderItemPo.getGroupBuyOrderId();
            AppGroupBuyOrderDetailVo appGroupBuyOrderDetailVo = getAppGroupBuyOrderDetailVoByGroupBuyOrderId(groupBuyOrderId, userId);
            if (GroupBuyOrderItemStatusEnum.PAID.getValue() == groupBuyOrderItemPo.getStatus()) {
                appGroupBuyOrderDetailVo.setInviteEnable(true);
            }
            return appGroupBuyOrderDetailVo;
        } else if (appGroupBuyOrderDetailQueryDto.getGroupBuyOrderId() != null) {
            // 拼团邀请码分享，groupBuyOrderId有值
            Long groupBuyOrderId = appGroupBuyOrderDetailQueryDto.getGroupBuyOrderId();
            return getAppGroupBuyOrderDetailVoByGroupBuyOrderId(groupBuyOrderId, userId);
        }
        throw new BusinessException("请求参数错误");
    }

    private AppGroupBuyOrderDetailVo getAppGroupBuyOrderDetailVoByGroupBuyOrderId(Long groupBuyOrderId, Long currentUserId) {
        TbGroupBuyOrderPo groupBuyOrderPo = groupBuyOrderMapper.selectById(groupBuyOrderId);
        // 活动信息
        ActiveVo activeVo = activeApi.getById(groupBuyOrderPo.getActiveId()).unpack();
        ActiveGroupBuyVo activeGroupBuyVo = activeApi.getGroupBuyActiveByActiveId(groupBuyOrderPo.getActiveId()).unpack();

        AppGroupBuyOrderDetailVo appGroupBuyOrderDetailVo = new AppGroupBuyOrderDetailVo();
        appGroupBuyOrderDetailVo.setGroupBuyOrderId(groupBuyOrderPo.getId());
        appGroupBuyOrderDetailVo.setActiveTitle(activeVo.getActiveTitle());
        appGroupBuyOrderDetailVo.setActiveImg(activeVo.getActiveImg());
        appGroupBuyOrderDetailVo.setActivePrice(activeVo.getActivePrice());
        appGroupBuyOrderDetailVo.setOriginPrice(activeVo.getOriginPrice());
        appGroupBuyOrderDetailVo.setGroupBuyPrice(activeGroupBuyVo.getGroupBuyPrice());
        appGroupBuyOrderDetailVo.setGroupNum(groupBuyOrderPo.getGroupNum());
        appGroupBuyOrderDetailVo.setCurrentNum(groupBuyOrderPo.getCurrentNum());
        appGroupBuyOrderDetailVo.setExpiredTime(groupBuyOrderPo.getExpiredTime());
        appGroupBuyOrderDetailVo.setFreeType(groupBuyOrderPo.getFreeType());
        appGroupBuyOrderDetailVo.setGroupLeadState(Objects.equals(currentUserId, groupBuyOrderPo.getLeadUserId()));
        // 是否可邀请拼团
        appGroupBuyOrderDetailVo.setInviteEnable(false);
        // 活动开始结束时间
        appGroupBuyOrderDetailVo.setActiveStartTime(activeVo.getStartTime());
        appGroupBuyOrderDetailVo.setActiveEndTime(activeVo.getEndTime());
        // 团员列表
        GroupMembersQueryDto groupMembersQueryDto = new GroupMembersQueryDto();
        groupMembersQueryDto.setGroupBuyOrderId(groupBuyOrderPo.getId());
        List<GroupBuyMemberVo> groupMembers = listGroupMembers(groupMembersQueryDto);
        appGroupBuyOrderDetailVo.setMembers(groupMembers);

        return appGroupBuyOrderDetailVo;
    }

    @Override
    public List<PendingGroupOrderVo> listPendingGroupBuyOrders(Long activeId, Long userId) {
        List<TbGroupBuyOrderPo> tbGroupBuyOrderPos = groupBuyOrderMapper.selectPendingGroups(activeId);
        if (CollectionUtils.isEmpty(tbGroupBuyOrderPos)) {
            return Collections.emptyList();
        }
        List<Long> groupBuyOrderIds = tbGroupBuyOrderPos.stream()
                .map(TbGroupBuyOrderPo::getId).collect(Collectors.toList());
        Map<Long, List<TbGroupBuyOrderItemPo>> groupItemMap = getGroupItemMap(groupBuyOrderIds);

        List<PendingGroupOrderVo> resultList = new ArrayList<>(groupBuyOrderIds.size());
        for (TbGroupBuyOrderPo groupBuyOrderPo : tbGroupBuyOrderPos) {
            PendingGroupOrderVo pendingGroupOrderVo = BeanUtil.copyProperties(groupBuyOrderPo, PendingGroupOrderVo.class);
            pendingGroupOrderVo.setGroupBuyOrderId(groupBuyOrderPo.getId());
            List<TbGroupBuyOrderItemPo> tbGroupBuyOrderItemPos = groupItemMap.get(groupBuyOrderPo.getId());

            // 过滤已经参与的团
            Set<Long> groupUserIds = tbGroupBuyOrderItemPos.stream().map(TbGroupBuyOrderItemPo::getUserId).collect(Collectors.toSet());
            if (userId != null && groupUserIds.contains(userId)) {
                continue;
            }

            if (CollectionUtils.isNotEmpty(tbGroupBuyOrderItemPos)) {
                List<GroupBuyMemberVo> groupMembers = tbGroupBuyOrderItemPos.stream()
                        .map(e -> BeanUtil.copyProperties(e, GroupBuyMemberVo.class))
                        .collect(Collectors.toList());
                pendingGroupOrderVo.setMembers(groupMembers);
            }
            resultList.add(pendingGroupOrderVo);
        }
        return resultList;
    }

    @Override
    public List<GroupBuyMemberVo> listGroupMembers(GroupMembersQueryDto groupMembersQueryDto) {
        Long groupBuyOrderId = groupMembersQueryDto.getGroupBuyOrderId();
        List<TbGroupBuyOrderItemPo> tbGroupBuyOrderItems = groupBuyOrderItemMapper.selectByGroupBuyOrderId(groupBuyOrderId);
        List<TbGroupBuyOrderItemPo> paidOrderItems = tbGroupBuyOrderItems.stream()
                .filter(e -> e.getStatus() == GroupBuyOrderItemStatusEnum.PAID.getValue())
                .collect(Collectors.toList());
        List<GroupBuyMemberVo> groupMembers = paidOrderItems.stream()
                .map(e -> BeanUtil.copyProperties(e, GroupBuyMemberVo.class))
                .collect(Collectors.toList());

        // 报名信息团长是否可见
        if (groupMembersQueryDto.getViewEnrollInfo()) {
            TbGroupBuyOrderPo groupBuyOrderPo = groupBuyOrderMapper.selectById(groupBuyOrderId);
            ActiveGroupBuyVo activeGroupBuyVo = activeApi.getGroupBuyActiveByActiveId(groupBuyOrderPo.getActiveId()).unpack();
            // 是团长 & 拼团活动设置可查看报名信息
            if (activeGroupBuyVo.getLeadViewEnrollInfo() == 1
                    && Objects.equals(groupBuyOrderPo.getLeadUserId(), groupMembersQueryDto.getUserId())) {
                List<Long> orderIds = paidOrderItems.stream().map(TbGroupBuyOrderItemPo::getOrderId).collect(Collectors.toList());
                Map<Long, String> orderEnrollInfoMap = getOrderEnrollInfoMap(orderIds);
                for (GroupBuyMemberVo groupBuyMemberVo : groupMembers) {
                    String enrollInfoJson = orderEnrollInfoMap.get(groupBuyMemberVo.getOrderId());
                    groupBuyMemberVo.setEnrollInfos(OrderEnrollInfoUtil.parseEnrollInfos(enrollInfoJson));
                }
            }
        }

        return groupMembers;
    }

    @Override
    public List<GroupBuyOrderDetailVo> listDetailByOrderIds(List<Long> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return Collections.emptyList();
        }
        return groupBuyOrderItemMapper.selectByOrderIds(orderIds);
    }

    @Override
    public List<GroupBuyOrderNumStatVo> statisticsGroupOrderNumByActiveIds(List<Long> activeIds) {
        if (CollectionUtils.isEmpty(activeIds)) {
            return Collections.emptyList();
        }
        return groupBuyOrderMapper.statisticsGroupOrderNumByActiveIds(activeIds);
    }

    @Override
    public Page<GroupBuyOrderPageVo> page(GroupBuyOrderPageDto groupBuyOrderPageDto) {
        PageHelper.startPage(groupBuyOrderPageDto.getPageNum(), groupBuyOrderPageDto.getPageSize());
        if (groupBuyOrderPageDto.getStatus() == null) {
            List<Integer> statusList = Arrays.asList(
                    GroupBuyStatusEnum.PENDING.getValue(), GroupBuyStatusEnum.COMPLETED.getValue(), GroupBuyStatusEnum.FAILED.getValue());
            groupBuyOrderPageDto.setStatusList(statusList);
        }
        List<GroupBuyOrderPageVo> groupBuyOrderPageVos = groupBuyOrderMapper.selectPageByDto(groupBuyOrderPageDto);
        if (CollectionUtils.isEmpty(groupBuyOrderPageVos)) {
            return Page.empty(groupBuyOrderPageDto.getPageNum(), groupBuyOrderPageDto.getPageSize());
        }
        List<Long> groupBuyOrderIds = groupBuyOrderPageVos.stream()
                .map(GroupBuyOrderPageVo::getId).collect(Collectors.toList());

        GroupBuyOrderItemQueryDto itemQueryDto = new GroupBuyOrderItemQueryDto();
        itemQueryDto.setGroupBuyOrderIds(groupBuyOrderIds);
        itemQueryDto.setPaymentStatus(2);
//        itemQueryDto.setStatusList(Collections.singletonList(GroupBuyOrderItemStatusEnum.PAID.getValue()));
        List<TbGroupBuyOrderItemPo> tbGroupBuyOrderItemPos = groupBuyOrderItemMapper.selectByDto(itemQueryDto);
        Map<Long, List<TbGroupBuyOrderItemPo>> groupOrderIdToItems = tbGroupBuyOrderItemPos.stream()
                .collect(Collectors.groupingBy(TbGroupBuyOrderItemPo::getGroupBuyOrderId));

        for (GroupBuyOrderPageVo groupBuyOrderPageVo : groupBuyOrderPageVos) {
            Long groupBuyOrderId = groupBuyOrderPageVo.getId();
            List<TbGroupBuyOrderItemPo> itemPos = groupOrderIdToItems.getOrDefault(groupBuyOrderId, Collections.emptyList());
            List<TbGroupBuyOrderItemPo> sortItems = itemPos.stream()
                    .sorted(Comparator.comparing(TbGroupBuyOrderItemPo::getId)).collect(Collectors.toList());
            List<GroupBuyOrderItemVo> itemVos = new ArrayList<>(itemPos.size());
            for (int i=0; i<sortItems.size(); i++) {
                TbGroupBuyOrderItemPo itemPo = sortItems.get(i);
                GroupBuyOrderItemVo groupBuyOrderItemVo = BeanUtil.copyProperties(itemPo, GroupBuyOrderItemVo.class);
                groupBuyOrderItemVo.setItemNo(i + 1);
                if (groupBuyOrderItemVo.getOrderId() == null) {
                    groupBuyOrderItemVo.setOrderNo("0元开团");
                }
                itemVos.add(groupBuyOrderItemVo);
            }
            groupBuyOrderPageVo.setItems(itemVos);
        }

        PageInfo<GroupBuyOrderPageVo> pageInfo = new PageInfo<>(groupBuyOrderPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public TbGroupBuyOrderItemPo getGroupBuyOrderItemByOrderId(Long orderId) {
        return groupBuyOrderItemMapper.selectByOrderId(orderId);
    }

    @Override
    public void scanExpiredGroupBuyOrders() {
        List<TbGroupBuyOrderPo> expiredGroupBuyOrders = groupBuyOrderMapper.selectExpiredGroupBuyOrders();
        if (CollectionUtils.isEmpty(expiredGroupBuyOrders)) {
            return;
        }
        for (TbGroupBuyOrderPo groupBuyOrder : expiredGroupBuyOrders) {
            // 虚拟成团
            if (groupBuyOrder.getVirtualGroup() == 1) {
                handleVirtualGroupBuy(groupBuyOrder);
            } else {
                // 拼团失败
                handleGroupFail(groupBuyOrder);
            }
        }
    }

    // 虚拟成团处理
    private void handleVirtualGroupBuy(TbGroupBuyOrderPo groupBuyOrderPo) {
        log.info("拼团id: {} 虚拟成团", groupBuyOrderPo.getId());
        GroupBuyOrderItemQueryDto groupBuyOrderItemQueryDto = new GroupBuyOrderItemQueryDto();
        groupBuyOrderItemQueryDto.setGroupBuyOrderIds(Collections.singletonList(groupBuyOrderPo.getId()));
        groupBuyOrderItemQueryDto.setStatusList(Collections.singletonList(GroupBuyOrderItemStatusEnum.PAID.getValue()));
        List<TbGroupBuyOrderItemPo> tbGroupBuyOrderItemPos = groupBuyOrderItemMapper.selectByDto(groupBuyOrderItemQueryDto);
        // 还需要多少人成团
        int num = groupBuyOrderPo.getGroupNum() - tbGroupBuyOrderItemPos.size();
        List<String> virtualUserNames = UsernameGenerator.generateDescriptiveUsernames(num);

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());
        try {
            for (int i=0; i<num; i++) {
                TbGroupBuyOrderItemPo item = GroupBuyOrderConvert.wrapVirtualGroupBuyOrderItemPo(
                        groupBuyOrderPo.getId(), virtualUserNames.get(i));
                groupBuyOrderItemMapper.insert(item);
            }
            // 更新拼团主单为成团
            GroupOrderSuccessParam groupOrderSuccessParam = new GroupOrderSuccessParam();
            processForGroupSuccess(groupBuyOrderPo.getId(), groupOrderSuccessParam);

            transactionManager.commit(transaction);
        } catch (Exception e) {
            log.error("虚拟成团处理失败：" + e.getMessage(), e);
            transactionManager.rollback(transaction);
        }
    }

    // 拼团失败
    private void handleGroupFail(TbGroupBuyOrderPo groupBuyOrderPo) {
        log.info("拼团id: {} 拼团失败处理", groupBuyOrderPo.getId());
        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());
        try {
            // 更新主单 -> 失败
            groupBuyOrderPo.setStatus(GroupBuyStatusEnum.FAILED.getValue());
            groupBuyOrderPo.setUpdateTime(LocalDateTime.now());
            groupBuyOrderMapper.updateById(groupBuyOrderPo);

            GroupBuyOrderItemQueryDto groupBuyOrderItemQueryDto = new GroupBuyOrderItemQueryDto();
            groupBuyOrderItemQueryDto.setGroupBuyOrderIds(Collections.singletonList(groupBuyOrderPo.getId()));
            groupBuyOrderItemQueryDto.setStatusList(Collections.singletonList(GroupBuyOrderItemStatusEnum.PAID.getValue()));
            List<TbGroupBuyOrderItemPo> tbGroupBuyOrderItemPos = groupBuyOrderItemMapper.selectByDto(groupBuyOrderItemQueryDto);
            for (TbGroupBuyOrderItemPo item : tbGroupBuyOrderItemPos) {
                item.setStatus(GroupBuyOrderItemStatusEnum.CANCEL.getValue());
                item.setUpdateTime(LocalDateTime.now());
                groupBuyOrderItemMapper.updateById(item);
                // 取消订单
                cancelOrder(item, false);
            }
            transactionManager.commit(transaction);
        } catch (Exception e) {
            log.error("拼团失败处理失败：" + e.getMessage(), e);
            transactionManager.rollback(transaction);
        }
    }

    private void cancelOrder(TbGroupBuyOrderItemPo item, boolean fullRefund) {
        // 取消订单 & 退款
        if (item.getOrderId() != null && item.getOrderId() != 0) {
            CancelOrderDto cancelOrderDto = new CancelOrderDto();
            cancelOrderDto.setUserId(item.getUserId());
            cancelOrderDto.setOrderId(item.getOrderId());
            cancelOrderDto.setRefundType(RefundTypeEnum.GROUP_FAILED.getValue());
            orderService.cancelOrder(cancelOrderDto);
        }

        String content = null;
        if (item.getGroupLead() == 1 && StringUtils.isBlank(item.getOrderNo())) {
            content = String.format(MsgConstant.FAILED_ZERO_GROUP_BUY, item.getActiveTitle());
        } else {
            content = String.format(MsgConstant.FAILED_GROUP_BUY, item.getActiveTitle(), item.getOrderNo());
        }
        if (fullRefund) {
            content = String.format(MsgConstant.FAILED_GROUP_BUY_FULL);
        }
        sendNotifyMsg(item.getUserId(), NotifyMsgTypeEnum.FAILED_GROUP_BUY, content);
    }

    private void sendNotifyMsg(Long userId, NotifyMsgTypeEnum notifyMsgType, String content) {
        NotifyMsgSendDto notifyMsgSendDto = new NotifyMsgSendDto();
        notifyMsgSendDto.setUserId(userId);
        notifyMsgSendDto.setMsgType(notifyMsgType.getValue());
        notifyMsgSendDto.setRoleType(RoleTypeEnum.BUSINESS.getValue());
        notifyMsgSendDto.setContent(content);
        notifyMsgSendDto.setMsgState(NotifyMsgStateEnum.NO_READ.getValue());
        notifyMsgProvider.sendMsg(notifyMsgSendDto);
    }

    // 获取订单对应的报名信息，key=orderId, value=报名信息Json
    private Map<Long, String> getOrderEnrollInfoMap(List<Long> orderIds) {
        LambdaQueryWrapper<TbOrderItemPo> qw = Wrappers.<TbOrderItemPo>lambdaQuery()
                .in(TbOrderItemPo::getOrderId, orderIds)
                .isNotNull(TbOrderItemPo::getEnrollInfo);
        List<TbOrderItemPo> tbOrderItemPos = orderItemMapper.selectList(qw);
        if (CollectionUtils.isEmpty(tbOrderItemPos)) {
            return Collections.emptyMap();
        }
        Map<Long, String> resultMap = new HashMap<>();
        for (TbOrderItemPo item : tbOrderItemPos) {
            Long orderId = item.getOrderId();
            if (resultMap.containsKey(orderId)) {
                continue;
            }
            resultMap.put(orderId, item.getEnrollInfo());
        }
        return resultMap;
    }

    private Map<Long, List<TbGroupBuyOrderItemPo>> getGroupItemMap(List<Long> groupBuyOrderIds) {
        GroupBuyOrderItemQueryDto groupBuyOrderItemQueryDto = new GroupBuyOrderItemQueryDto();
        groupBuyOrderItemQueryDto.setGroupBuyOrderIds(groupBuyOrderIds);
        groupBuyOrderItemQueryDto.setStatusList(Collections.singletonList(GroupBuyOrderItemStatusEnum.PAID.getValue()));
        List<TbGroupBuyOrderItemPo> tbGroupBuyOrderItemPos = groupBuyOrderItemMapper.selectByDto(groupBuyOrderItemQueryDto);
        return tbGroupBuyOrderItemPos.stream()
                .collect(Collectors.groupingBy(TbGroupBuyOrderItemPo::getGroupBuyOrderId));
    }

    private void validateGroupBuyOrder(TbGroupBuyOrderPo groupBuyOrderPo) {
        // 拼团是否到期
        if (groupBuyOrderPo.getExpiredTime().isBefore(LocalDateTime.now())) {
            Throw.isBusinessException("该团已失效");
        }
        // 是否满员
        if (Objects.equals(groupBuyOrderPo.getCurrentNum(), groupBuyOrderPo.getGroupNum())) {
            Throw.isBusinessException("该团已满员");
        }
    }

    // 校验开团权限
    private void validateGroupCreatorPermission(Long activeId, Long userId) {
        // 参团则无需校验
        ActiveGroupBuyVo activeGroupBuyVo = activeApi.getGroupBuyActiveByActiveId(activeId).unpack();
        if (activeGroupBuyVo == null) {
            Throw.isBusinessException("拼团活动不存在");
        }
        if (GroupCreatorPermissionEnum.LEVEL1_AGENT.name().equals(activeGroupBuyVo.getGroupCreatorPermission())) {
            BusinessAgentVo businessAgentVo = businessAgentApi.getBusinessAgentById(activeGroupBuyVo.getBusinessId(), userId).unpack();
//            AppUserVo appUserVo = appUserApi.getById(userId).unpack();
            if (businessAgentVo == null) {
                Throw.isBusinessException("仅商家经纪人可开团");
            }

        }
    }

}
